package top.wilsonlv.jaguar.cloud.auth.extension.sms;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.util.StringUtils;
import top.wilsonlv.jaguar.cloud.auth.sdk.token.SmsAuthenticationToken;
import top.wilsonlv.jaguar.cloud.auth.sdk.token.SmsDTO;
import top.wilsonlv.jaguar.cloud.auth.security.LoginFailureHandler;
import top.wilsonlv.jaguar.cloud.auth.security.LoginSuccessHandler;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @author lvws
 * @since 2022/1/6
 */
@Slf4j
public class SmsAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    public static final String SMS_LOGIN_PATH = "/login/sms";

    private final SmsService smsService;


    public SmsAuthenticationFilter(SmsService smsService, AuthenticationManager authenticationManager,
                                   LoginSuccessHandler loginSuccessHandler, LoginFailureHandler loginFailureHandler) {
        super(new AntPathRequestMatcher(SMS_LOGIN_PATH, HttpMethod.POST.name()), authenticationManager);

        setAuthenticationSuccessHandler(loginSuccessHandler);
        setAuthenticationFailureHandler(loginFailureHandler);
        this.smsService = smsService;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (!request.getMethod().equals(HttpMethod.POST.name())) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        }

        SmsDTO smsDTO = smsService.request2DTO(request);
        if (!StringUtils.hasText(smsDTO.getPrincipal())) {
            throw new UsernameNotFoundException("手机号或邮箱为非空");
        }

        if (!StringUtils.hasText(smsDTO.getTicket())) {
            throw new BadCredentialsException("ticket为非空");
        }

        if (!StringUtils.hasText(smsDTO.getSmsCode())) {
            throw new BadCredentialsException("短信验证码为非空");
        }

        SmsAuthenticationToken authRequest = new SmsAuthenticationToken(smsDTO);
        // Allow subclasses to set the "details" property
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
        return this.getAuthenticationManager().authenticate(authRequest);
    }

}
